home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / tpu60.arc / TPU6REF.PAS < prev    next >
Pascal/Delphi Source File  |  1991-04-01  |  40KB  |  1,044 lines

  1. {$D+,L+,S+,R-,E-,N-}
  2. Unit tpu6ref;
  3.  
  4. { This Unit performs the analysis functions required to interpret and to
  5.   provide a print-out of the UNIT which reveals its meaning.  Included is
  6.   the support to identify and delineate the structures found in the main
  7.   symbol dictionary as well as a collection of information about relations
  8.   which may exist between generated code, constant and BSS data.  These are
  9.   obviously extremely interesting to the "Smart-Linker".
  10.  
  11.   The dictionary is unraveled by a non-recursive algorithm which follows
  12.   dictionary pointers until all targets have been identified.  This data
  13.   is relevant to the generated code, constant and BSS data as well.  This
  14.   unit utilizes Objects in its implementation but they aren't visible to the
  15.   calling program.  All structures maintained by this unit are private and
  16.   allocated on the heap.  Great care is exercised to minimize utilization
  17.   of heap storage.  The initial dictionary survey allocates sufficient heap
  18.   storage to complete its task.  It then truncates the allocation to exactly
  19.   the amount of storage that must be retained.  The caller can instruct this
  20.   unit to de-allocate its stored data at any time.  Any number of units can
  21.   be analyzed (limited only by heap space) since the data for each unit is
  22.   managed by a master Object intended for just that purpose.
  23.  
  24.   The dictionary analysis may be retrieved sequentially.  The Map analyses
  25.   may be retrieved randomly.  The PROC Map analysis may be sorted into two
  26.   distinct sequences for specialized retrieval problems.
  27.  
  28.   These functions are encapsulated in this unit to dissociate them from the
  29.   very low-level functions of the other units and from the main program.
  30.  
  31.   The program is drifting toward this more modular functional organization
  32.   to ease maintenance and to better support the concept of re-usability.
  33.  
  34.   The PRIMARY emphasis here is on safety - not speed - although at least
  35.   one of the routines was speeded-up via inline assembler.
  36.  
  37.   }
  38.  
  39. (*****************)                                             {.CP47}
  40. (**) Interface (**)             Uses TPU6AMS;
  41. (*****************)
  42.  
  43. Type
  44.      CoverId = (cvName,         { Dictionary Entry Headers }
  45.                 cvHash,         { Hash Tables              }
  46.                 cvType,         { Type Descriptors         }
  47.                 cvINLN,         { INLINE Code Bytes        }
  48.                 cvNULL);        { terminating status       }
  49.  
  50.      SurveyRecPtr = ^ SurveyRec;  { Output of Survey }
  51.      SurveyRec = RECORD
  52.         LocLL  : LL;       { LL to location of data structure      }
  53.     LocOwn : LL;       { LL to Dictionary Header of Owner or 0 }
  54.     LocTyp : CoverId;  { Class of Structure (see above)        }
  55.         LocNxt : LL;       { LL to location of following structure }
  56.         LocLvl : Word;     { Nesting Level of entry                }
  57.      END;
  58.  
  59. PROCEDURE SurveyUnit      (U   : UnitPtr);   { Performs Analysis }
  60.  
  61. PROCEDURE FetchNextSurvey (U   : UnitPtr;    { Gets Dictionary Survey }
  62.                          VAR S : SurveyRec); { Results Sequentially   }
  63.  
  64. PROCEDURE PurgeUnitSurvey (U   : UnitPtr);   { Purges Analysis From Heap }
  65.  
  66. Type
  67.  
  68.      MapFlags = (mfNULL,         { Undefined / Unused Entry       }
  69.                  mfINTF,         { INTERFACE CONST/VAR Map Entry  }
  70.                  mfIMPL,         { IMPLEMENTATION CONST/VAR Map   }
  71.                  mfNEST,         { NESTED Scope Typed CONST DSeg  }
  72.                  mfXTRN,         { EXTERNAL CONST/VAR DSeg        }
  73.                  mfTVMT,         { VMT Template in CONST Map      }
  74.                  mfPROC,         { PROC Map Entry                 }
  75.                  mfCSEG);        { CSEG Map Entry                 }
  76.  
  77.      MapRefRecPtr = ^ MapRefRec;  { Output of VAR/CONST Map Survey }
  78.      MapRefRec = RECORD                                             
  79.     MapTyp : MapFlags; { Defining Scope Category (see above)   }
  80.         MapOfs : Word;     { Offset within Map Table               }
  81.     MapOwn : LL;       { DNAME of Parent Scope / PROC          }
  82.         MapSrc : LL;       { Offset in Source File Table           }
  83.         MapLod : LL;       { Load Point for CODE/CONST Segment     }
  84.         MapSiz : Word;     { Size of Segment / PROC (Bytes)        }
  85.  
  86.      CASE MapFlags OF
  87.         mfCSEG: (                    {--CSEG/CONST Map Table Only--}
  88.                   MapFxI : LL;       { Segment Fix-Up (Initial)    }
  89.                   MapFxJ : LL;       { Segment Fix-Up (Final)      }
  90.                 );
  91.         mfPROC: (                    {-----PROC Map Table Only-----}
  92.                   MapEPT : LL;       { Entry Point for PROC        }
  93.                   MapCSM : LL;       { Offset in CSEG Map for PROC }
  94.                 );
  95.      END;
  96.  
  97.      SortMode = (CSegOrder,      { Sort Proc Map into CSeg Order }
  98.                  PMapOrder);     { Sort Proc Map into Proc Order }
  99.  
  100. PROCEDURE SortProcRefs  (  U   : UnitPtr;    { Sorts PROC Map as Needed  }
  101.                          Mode  : SortMode);
  102.  
  103. PROCEDURE FetchVARsRef  (VAR S : MapRefRec;  { Gets GLOBAL Var Analysis  }
  104.                            U   : UnitPtr;    { Using Natural Map Offsets }
  105.                          Offset: Word);
  106.  
  107. PROCEDURE FetchCONsRef  (VAR S : MapRefRec;  { Gets Typed CONST Analysis }
  108.                            U   : UnitPtr;    { Using Natural Map Offsets }
  109.                          Offset: Word);
  110.  
  111. PROCEDURE FetchCSegRef  (VAR S : MapRefRec;  { Gets CSeg Map Analysis    }
  112.                            U   : UnitPtr;    { Using Natural Map Offsets }
  113.                          Offset: Word);
  114.  
  115. PROCEDURE FetchProcRef  (VAR S : MapRefRec;  { Gets PROC Map Analysis    }
  116.                            U   : UnitPtr;    { Using Natural Map Offsets }
  117.                          Offset: Word);
  118.  
  119. (**********************)                                        {.CP32}
  120. (**) Implementation (**)
  121. (**********************)
  122.  
  123. Type
  124.      CvrRecPtr = ^ CvrRec;
  125.      CvrRec = RECORD
  126.         LocLL  : LL;       { LL to location of data structure      }
  127.     LocOwn : LL;       { LL to Dictionary Header of Owner or 0 }
  128.     LocTyp : CoverId;  { Type of Structure                     }
  129.         LocLvl : Word;     { Entry Nesting Level in Dictionary     }
  130.      END;
  131.  
  132.      CvrTabPtr = ^ CvrTab;
  133.      CvrTab = ARRAY[1..2] OF CvrRec;  { Model of Stack/Queue }
  134.  
  135.      MapTabPtr = ^ MapTab;
  136.      MapTab = ARRAY[0..4] OF MapRefRec; { Model of Cross-Refs  }
  137.  
  138.      RMapPtr = ^ RMap;
  139.      RMap = Object
  140.        RMapTabPtr : MapTabPtr;   { To Map References }
  141.        RMapTabSiz : LongInt;     { Reference Counter }
  142.        Destructor  Done;
  143.        Constructor Init(Width : Word);
  144.        Procedure   SortPmap(Mode : SortMode);
  145.        Procedure   FetchRef(VAR S : MapRefRec; Offset : Word);
  146.        Procedure   StoreRef(    S : MapRefRec; Offset : Word);
  147.      End;
  148.  
  149.      TMapPtr = ^ TMap;
  150.      TMap = Object
  151.        TMapConPtr : RMapPtr;     { To DSEG Map Survey (CONST) }
  152.        TMapVarPtr : RMapPtr;     { To DSEG Map Survey (VAR)   }
  153.        TMapProPtr : RMapPtr;     { To PROC Map Survey         }
  154.        TMapCodPtr : RMapPtr;     { To CSEG Map Survey         }
  155.        Destructor  Done;
  156.        Constructor Init(U : UnitPtr);
  157.      End;  { TMap }
  158.  
  159.      CoverPtr = ^ Cover;                                        {.CP37}
  160.      Cover = Object
  161.        CvrNxtPtr : CoverPtr;    { To Next Cover in Chain }
  162.        CvrUnitPt : UnitPtr;     { To Unit Being Surveyed }
  163.        CvrMapPtr : TMapPtr;     { To Map Analysis Object }
  164.        CvrStkPtr : CvrTabPtr;   { To Cover Stack         }
  165.        CvrQuePtr : CvrTabPtr;   { To Completed Survey    }
  166.        CvrSize   : Longint;     { Allocation Sizes       }
  167.        CvrStkTop,               { Cover Stack Top        }
  168.        CvrStkBot,               { Cover Stack Bottom     }
  169.        CvrStkMax,               { Cover Stack Ceiling    }
  170.        CvrQueHead,              { Cover Queue Head       }
  171.        CvrQueTail,              { Cover Queue Tail       }
  172.        CvrQueMax  : Word;       { Cover Queue Ceiling    }
  173.        Destructor  Done;
  174.        Constructor Init(U : UnitPtr; Next : CoverPtr);
  175.        Procedure   DisposeStack;
  176.        Procedure   DisposeQueue;
  177.        Procedure   PackQueue;
  178.        Procedure   CalcCovers;
  179.        Procedure   IndexMaps;
  180.        FUNCTION    QueuePos(Locn : LL) : Word;
  181.        PROCEDURE   EnQueue(Arg : CvrRec);
  182.        FUNCTION    Queued(Key : LL) : Boolean;
  183.        PROCEDURE   Push(ArgLoc,ArgOwn : LL; ArgTyp : CoverId; ArgLvl:Word);
  184.        PROCEDURE   Pop(VAR Arg : CvrRec);
  185.      End;  { Cover }
  186.  
  187. Const RecLen = SizeOf(MapRefRec); MapLen = SizeOf(DMapRec);
  188.       CvrRoot : CoverPtr = Nil; CvrLocus : CoverPtr = Nil;
  189.       NullMap : MapRefRec = (MapTyp: mfNULL; MapOfs: 0;
  190.                              MapOwn: $FFFF;  MapSrc: 0;
  191.                              MapLod: 0;      MapSiz: 0;
  192.                              MapEPT: 0;      MapCSM: 0);
  193.  
  194. VAR   CvrWork : CvrRec;
  195.  
  196.  
  197.      {   Begin Methods for   R M a p   }                        {.CP17}
  198.  
  199.      Constructor RMap.Init(Width : Word);
  200.      Var I : Word; S : MapRefRec;
  201.      Begin
  202.         RMapTabPtr := Nil; RMapTabSiz := Width DIV SizeOf(DMapRec);
  203.         IF RMapTabSiz > 0 Then
  204.         Begin
  205.            GetMem(RMapTabPtr,RMapTabSiz * SizeOf(MapRefRec));
  206.            S := NullMap;
  207.            For I := 0 To RMapTabSiz-1 Do
  208.            Begin
  209.               RMapTabPtr^[i] := S;
  210.               Inc(S.MapOfs,SizeOf(DMapRec));
  211.            End;
  212.         End;
  213.      End;
  214.  
  215.      Destructor RMap.Done;                                      {.CP05}
  216.      Begin
  217.         IF RMapTabSiz > 0
  218.         Then FreeMem(RMapTabPtr,RMapTabSiz * RecLen)
  219.      End;
  220.  
  221.      Procedure RMap.SortPmap(Mode: SortMode);                   {.CP21}
  222.      Var Rmt: MapTabPtr; I, J, K : Word; W: MapRefRec;
  223.      Begin
  224.         Rmt := RMapTabPtr; I := 0;
  225.         If Rmt <> Nil Then
  226.         Repeat                             { Slow but simple sort }
  227.            J := I + 1; K := I;
  228.            While J < RMapTabSiz Do Begin
  229.               Case Mode Of
  230.                 CSegOrder:
  231.                    If Rmt^[J].MapCSM < Rmt^[K].MapCSM
  232.                      Then K := J
  233.                      Else
  234.                    If Rmt^[J].MapCSM = Rmt^[K].MapCSM
  235.                      Then
  236.                        If Rmt^[J].MapEPT < Rmt^[K].MapEPT
  237.                        Then K := J;
  238.  
  239.                 PMapOrder:
  240.                   If Rmt^[J].MapOfs < Rmt^[K].MapOfs Then K := J;
  241.               End; {Case}
  242.               Inc(J);
  243.            End;    {While}
  244.            If K <> I Then    { We need to do a swap }
  245.            Begin
  246.               W := Rmt^[I]; Rmt^[I] := Rmt^[K]; Rmt^[K] := W
  247.            End;
  248.            Inc(I);
  249.         Until I >= RMapTabSiz;
  250.      End; {SortPMap}
  251.  
  252.      Procedure RMap.FetchRef(VAR S : MapRefRec; Offset : Word); {.CP10}
  253.      Var I : Word;
  254.      Begin
  255.         If (Offset MOD MapLen) = 0
  256.         Then I := Offset Div MapLen
  257.         Else I := RMapTabSiz;
  258.         If NOT (I < RMapTabSiz)
  259.         Then S := NullMap
  260.         Else S := RMapTabPtr^[I];
  261.      End;
  262.  
  263.      Procedure   RMap.StoreRef(S : MapRefRec; Offset : Word);   {.CP09}
  264.      Var I : Word;
  265.      Begin
  266.         If (Offset MOD MapLen) = 0
  267.         Then I := Offset Div MapLen
  268.         Else I := RMapTabSiz;
  269.         If (I < RMapTabSiz)
  270.         Then RMapTabPtr^[I] := S
  271.      End;
  272.  
  273.      {   Begin  Methods For   T M A P   }                       {.CP09}
  274.  
  275.      Destructor  TMap.Done;
  276.      Begin
  277.         TMapConPtr^.Done;
  278.         TMapVarPtr^.Done;
  279.         TMapProPtr^.Done;
  280.         TMapCodPtr^.Done;
  281.      End;
  282.  
  283.      Constructor TMap.Init(U : UnitPtr);                        {.CP09}
  284.      Begin
  285.         TMapConPtr := New(RMapPtr,Init(U^.UHDMT-U^.UHTMT));
  286.         TMapVarPtr := New(RMapPtr,Init(U^.UHxxy-U^.UHDMT));
  287.         TMapProPtr := New(RMapPtr,Init(U^.UHCMT-U^.UHPMT));
  288.         TMapCodPtr := New(RMapPtr,Init(U^.UHTMT-U^.UHCMT));
  289.      End;
  290.  
  291.      {   Begin  Methods For   C O V E R   }                     {.CP14}
  292.  
  293. Constructor Cover.Init(U : UnitPtr; Next : CoverPtr);
  294. Begin
  295.    CvrStkTop  := 0;     CvrStkBot  := 0;        CvrStkMax := 0;
  296.    CvrQueTail := 0;     CvrQueHead := 0;        CvrQueMax := 0;
  297.    CvrNxtPtr  := Next;  CvrUnitPt  := U;
  298.    CvrStkPtr  := Nil;   CvrQuePtr  := Nil;
  299.    CvrSize := (U^.UHPMT-U^.UHIHT) + SizeOf(CvrRec) - 1;
  300.    CvrSize := CvrSize-(CvrSize MOD SizeOf(CvrRec));
  301.    GetMem(CvrQuePtr,CvrSize);
  302.    GetMem(CvrStkPtr,CvrSize);
  303.    CvrMapPtr := Nil;
  304. End;  {Cover.Init}
  305.  
  306. Procedure Cover.DisposeStack;                                  {.CP05}
  307. Begin
  308.    If CvrStkPtr <> Nil Then FreeMem(CvrStkPtr,CvrSize);
  309.    CvrStkPtr := Nil
  310. End;
  311.  
  312. Procedure Cover.DisposeQueue;                                  {.CP05}
  313. Begin
  314.    If CvrQuePtr <> Nil Then FreeMem(CvrQuePtr,CvrSize);
  315.    CvrQuePtr := Nil
  316. End;
  317.  
  318. Procedure Cover.PackQueue; { Releases un-used part of queue }   {.CP15}
  319. Var T, K : Word; P : Pointer;
  320. Begin
  321.    If CvrQuePtr <> Nil Then
  322.    Begin
  323.       T := CvrQueTail * SizeOf(CvrRec);
  324.       If T < CvrSize Then
  325.       Begin
  326.          K := (CvrSize - T) AND $FFF8;
  327.          P := PtrNormal(@CvrQuePtr^[CvrQueTail+1]);
  328.          FreeMem(P,K);               { VER60 Requires P be Normalized }
  329.          CvrSize := CvrSize - K;
  330.       End;
  331.    End;
  332. End;   {Cover.PackQueue}
  333.  
  334. Destructor  Cover.Done;                                         {.CP02}
  335. Begin DisposeStack; DisposeQueue; CvrMapPtr^.Done End;
  336.  
  337. FUNCTION Cover.QueuePos(Locn : LL):Word;            {.CP16}
  338. VAR Lo, Mid, Hi : Word;
  339. BEGIN
  340.    IF CvrQueTail < 1 THEN QueuePos := 1 ELSE
  341.    BEGIN
  342.       Lo := 1; Hi := CvrQueTail;
  343.       REPEAT
  344.          Mid := Longint(Lo + Hi) SHR 1;
  345.      IF Locn > CvrQuePtr^[Mid].LocLL
  346.      THEN Lo := Mid + 1
  347.      ELSE Hi := Mid - 1
  348.       UNTIL (CvrQuePtr^[Mid].LocLL=Locn) OR (Lo > Hi);
  349.       IF Locn > CvrQuePtr^[Mid].LocLL THEN Inc(Mid);
  350.       QueuePos := Mid;
  351.    END;     {WITH}
  352. END; {QueuePos}
  353.  
  354. PROCEDURE Cover.EnQueue(Arg : CvrRec);                      {.CP40}
  355. VAR I,J,K,L, Key : LL;
  356. BEGIN
  357.    Key := QueuePos(Arg.LocLL);
  358.    IF Arg.LocLL < CvrUnitPt^.UHPMT THEN
  359.    IF Key > CvrQueTail THEN
  360.    BEGIN
  361.       Inc(CvrQueTail);
  362.       CvrQuePtr^[CvrQueTail] := Arg
  363.    END ELSE
  364.    IF Arg.LocLL <> CvrQuePtr^[Key].LocLL THEN { Raise higher entries to }
  365.    BEGIN                                      { make room for insertion }
  366.       Inc(CvrQueTail);                    
  367.       I := Seg(CvrQuePtr^[CvrQueTail]);   { Segment of Tail Entry   }
  368.       J := Ofs(CvrQuePtr^[CvrQueTail]);   { Offset  of Tail Entry   }
  369.       K := Ofs(CvrQuePtr^[Key]);          { Offset to insert point  }
  370.       L := SizeOf(CvrRec);              { Size of Cover Record    }
  371.       ASM            { ASM used for speed only - can be done with FOR Loop }
  372.          PUSH DS                                       { Save DS for Turbo }
  373.          MOV  BX,J                           { Ofs(CvrQuePtr^[CvrQueTail]) }
  374.          MOV  CX,BX                                           { Copy To CX }
  375.          DEC  BX                                        { Back Down 1 Byte }
  376.          MOV  SI,BX                        { Ofs(CvrQuePtr^[CvrQueTail])-1 }
  377.          MOV  AX,L                                        { SizeOf(CvrRec) }
  378.          MOV  DI,BX                        { Ofs(CvrQuePtr^[CvrQueTail])-1 }
  379.          ADD  DI,AX                                      { +SizeOf(CvrRec) }
  380.          SUB  CX,K      { Ofs(CvrQuePtr^[CvrQueTail])-Ofs(CvrQuePtr^[Key]) }
  381.          MOV  AX,I                           { Seg(CvrQuePtr^[CvrQueTail]) }
  382.          MOV  ES,AX                                   { Set Target Segment }
  383.          MOV  DS,AX                                   { Set Source Segment }
  384.          STD                                 { Set Direction Right-To-Left }
  385.          REPNZ MOVSB                                     { Raise the queue }
  386.          POP  DS                                    { Restore DS for Turbo }
  387.       END;                                              { Replacement Ends }
  388.       CvrQuePtr^[Key] := Arg
  389.    END;
  390.    WITH CvrQuePtr^[Key] DO
  391.    IF LocOwn = 0 THEN LocOwn := Arg.LocOwn;
  392.    IF CvrQueTail > CvrQueMax THEN CvrQueMax := CvrQueTail;
  393. END; {EnQueue}
  394.  
  395. PROCEDURE Cover.Push( ArgLoc, ArgOwn : LL;                      {.CP13}
  396.                       ArgTyp : CoverId; ArgLvl : Word);
  397. VAR Arg : CvrRec;
  398. BEGIN
  399.    Arg.LocLL  := ArgLoc; Arg.LocOwn := ArgOwn;
  400.    Arg.LocTyp := ArgTyp; Arg.LocLvl := ArgLvl;
  401.    BEGIN
  402.       Inc(CvrStkTop);
  403.       IF CvrStkTop > CvrStkMax
  404.       THEN CvrStkMax := CvrStkTop;
  405.       CvrStkPtr^[CvrStkTop] := Arg
  406.    END
  407. END; {Push}
  408.  
  409. PROCEDURE Cover.Pop(VAR Arg : CvrRec);                        {.CP05}
  410. BEGIN
  411.    Arg := CvrStkPtr^[CvrStkTop];
  412.    Dec(CvrStkTop);
  413. END; {Pop}
  414.  
  415. FUNCTION Cover.Queued(Key : LL):Boolean;            {.CP11}
  416. VAR Loc : Word;
  417. BEGIN
  418.    Loc := QueuePos(Key);
  419.    IF Loc > CvrQueTail
  420.    THEN Queued := False
  421.    ELSE
  422.      IF Key = CvrQuePtr^[Loc].LocLL
  423.      THEN Queued := True
  424.      ELSE Queued := False
  425. END; {Queued}
  426.  
  427. Procedure Cover.CalcCovers;                                    {.CP03}
  428.  
  429.    PROCEDURE CoverWrapUp;
  430.  
  431.       PROCEDURE CoverWrapPost(x,s:LL);                         {.CP09}
  432.       VAR J : LL;
  433.       BEGIN
  434.          j := QueuePos(s);
  435.      WITH CvrQuePtr^[j] DO
  436.      IF LocLL = s THEN
  437.      IF (LocOwn > x) OR (LocOwn = 0)
  438.      THEN LocOwn := x;
  439.       END; {CoverWrapPost}
  440.  
  441.       PROCEDURE CoverWrapType(x : LL);                         {.CP27}
  442.       VAR D : DNamePtr; S : DStubPtr; T : TypePtr; i,j,k : LL;
  443.          RP : VarStubPtr; DF : Char;
  444.       BEGIN
  445.          D := AddrDict(CvrUnitPt,x);            { Q entry  }
  446.      S := AddrStub(D);                      { its stub }
  447.          RP := @S^.sRVF;
  448.      T := AddrType(CvrUnitPt,S^.sQTD);
  449.      IF T <> Nil THEN                       { TD in this unit }
  450.      BEGIN
  451.             DF := Public(D^.DForm);
  452.         CoverWrapPost(x,S^.sQTD.UntLL);
  453.         IF (T^.tpTC = 2) OR (T^.tpTC = 3) THEN
  454.         BEGIN
  455.            i := T^.RecdDict;
  456.            IF i <> x THEN
  457.            WHILE i <> 0 DO BEGIN
  458.               CoverWrapPost(x,i);
  459.           D := AddrDict(CvrUnitPt,i);
  460.           S := AddrStub(D);
  461.           IF DF = 'R' THEN i := RP^.ROB ELSE
  462.           IF DF = 'S' THEN i := S^.sSHT
  463.           ELSE i := 0;
  464.            END  {While I}
  465.         END
  466.      END  {IF T <> Nil}
  467.       END;    {CoverWrapType}
  468.  
  469.    VAR i : Integer;                                             {.CP08}
  470.    BEGIN {CoverWrapUp}
  471.       For i := 1 TO CvrQueTail DO
  472.       WITH CvrQuePtr^[i] DO
  473.       IF LocTyp = cvName THEN
  474.       IF Public(AddrDict(CvrUnitPt,LocLL)^.DForm) = 'Q'
  475.       THEN CoverWrapType(LocLL)
  476.    END;    {CoverWrapUp}
  477.  
  478.    PROCEDURE CoverType(Arg : CvrRec);                    {.CP51}
  479.    VAR T, TT : TypePtr; H:HashPtr; TTL : LL; I : Integer; L : Word;
  480.    BEGIN {CoverType}
  481.       T := TypePtr(PtrAdjust(CvrUnitPt,Arg.LocLL));
  482.       TTL := Arg.LocLL;
  483.       IF T <> Nil THEN
  484.       WITH T^ DO
  485.       CASE tpTC OF
  486.          $01: BEGIN
  487.              IF AddrType(CvrUnitPt,BaseType) <> Nil
  488.                     THEN Push(BaseType.UntLL,0,cvType,L);
  489.          IF AddrType(CvrUnitPt,BounDesc) <> Nil
  490.                     THEN Push(BounDesc.UntLL,0,cvType,L);
  491.           END; {CASE $01}
  492.      $02: IF RecdHash <> 0
  493.                  THEN Push(RecdHash,Arg.LocOwn,cvHash,L+1);
  494.      $03: IF ObjtHash <> 0
  495.                  THEN Push(ObjtHash,ObjtName,cvHash,L+1);
  496.      $04,
  497.          $05: IF AddrType(CvrUnitPt,FileType) <> Nil
  498.                  THEN Push(FileType.UntLL,0,cvType,L);
  499.      $06: BEGIN
  500.              IF AddrType(CvrUnitPt,T^.PFRes) <> Nil
  501.                     THEN Push(T^.PFRes.UntLL,Arg.LocOwn,cvType,L);
  502.          { Handle Parameter List Entries Here }
  503.          FOR I := 1 TO T^.PNPrm DO WITH T^.PFPar[I] DO
  504.          IF AddrType(CvrUnitPt,fPTD) <> Nil
  505.                     THEN Push(fPTD.UntLL,Arg.LocOwn,cvType,L);
  506.           END; {CASE $06}
  507.      $07: IF AddrType(CvrUnitPt,SetBase) <> Nil
  508.                  THEN Push(SetBase.UntLL,0,cvType,L);
  509.      $08: IF AddrType(CvrUnitPt,PtrBase) <> Nil
  510.                  THEN Push(PtrBase.UntLL,0,cvType,L);
  511.      $09: BEGIN
  512.              IF AddrType(CvrUnitPt,StrBase) <> Nil
  513.                     THEN Push(StrBase.UntLL,0,cvType,L);
  514.          IF AddrType(CvrUnitPt,StrBound) <> Nil
  515.                     THEN Push(StrBound.UntLL,0,cvType,L);
  516.           END; {CASE $09}
  517.      $0C, $0D,
  518.      $0E: IF AddrType(CvrUnitPt,Cmpat) <> Nil
  519.                  THEN Push(Cmpat.UntLL,0,cvType,L);
  520.      $0F: BEGIN
  521.              IF AddrType(CvrUnitPt,Cmpat) <> Nil
  522.                     THEN Push(Cmpat.UntLL,0,cvType,L);
  523.          { now stack the SET descriptor that follows }
  524.          TT := TypePtr(PtrAdjust(@Cmpat,SizeOf(T^.Cmpat)));
  525.          Push(FormLL(CvrUnitPt,TT),0,cvType,L);
  526.           END; {CASE $0F}
  527.       END;  {CASE tpTC}
  528.    END;  {CoverType}
  529.  
  530.    PROCEDURE CoverDictStub(D : DNamePtr;            {.CP38}
  531.                            S : DStubPtr; Owner : LL; L : Word);
  532.  
  533.    VAR T : TypePtr; H : HashPtr; I : Integer; LLDE : LL; C : Char;
  534.    BEGIN {CoverDictStub}
  535.       C := Public(D^.DForm);
  536.       LLDE := FormLL(CvrUnitPt,D);
  537.       WITH S^ DO
  538.       CASE C OF
  539.          'P': IF AddrType(CvrUnitPt,sPTD) <> Nil
  540.                  THEN Push(sPTD.UntLL,0,cvType,L);
  541.      'Q': IF AddrType(CvrUnitPt,sQTD) <> Nil
  542.                  THEN Push(sQTD.UntLL,LLDE,cvType,L);
  543.      'X': IF AddrType(CvrUnitPt,sQTD) <> Nil
  544.                  THEN Push(sQTD.UntLL,0,cvType,L);
  545.      'R': IF AddrType(CvrUnitPt,sRTD) <> Nil
  546.                  THEN Push(sRTD.UntLL,0,cvType,L);
  547.      'S': BEGIN
  548.              IF sSHT <> 0 THEN Push(sSHT,LLDE,cvHash,L+1);
  549.          T := AddrProcType(S);
  550.          Push(FormLL(T,CvrUnitPt),LLDE,cvType,L);
  551.          IF AddrType(CvrUnitPt,T^.PFRes) <> Nil
  552.                     THEN Push(T^.PFRes.UntLL,0,cvType,L);
  553.          { Handle Parameter List Entries Here }
  554.          FOR I := 1 TO T^.PNPrm DO WITH T^.PFPar[I] DO
  555.          IF AddrType(CvrUnitPt,fPTD) <> Nil
  556.                     THEN Push(fPTD.UntLL,0,cvType,L);
  557.          IF (sSTp AND $02) <> 0 THEN
  558.          Push(FormLL(CvrUnitPt,@T^.PFPar[T^.PNPrm+1]),LLDE,cvINLN,L);
  559.           END; {CASE 'S'}
  560.  
  561.      'Y': BEGIN
  562.              IF sYNU <> 0 THEN Push(sYNU,0,cvName,L);
  563.          IF sYPU <> 0 THEN Push(sYPU,0,cvName,L);
  564.           END; {CASE 'Y'}
  565.  
  566.       END; {CASE D^.DForm}
  567.    END;  {CoverDictStub}
  568.  
  569.    PROCEDURE CoverDictHdr(Arg : CvrRec);                      {.CP08}
  570.    VAR D : DNamePtr; S : DStubPtr;
  571.    BEGIN {CoverDictHdr}
  572.       D := AddrDict(CvrUnitPt,Arg.LocLL);
  573.       S := AddrStub(D);
  574.       CoverDictStub(D,S,Arg.LocLL,Arg.LocLvl);
  575.       IF D^.HLink <> 0 Then Push(D^.HLink,Arg.LocOwn,cvName,Arg.LocLvl);
  576.    END; {CoverDictHdr}
  577.  
  578.    PROCEDURE CoverHashTab(Arg : CvrRec);                      {.CP09}
  579.    VAR HLim, I : LL; H : HashPtr; L : Word;
  580.    BEGIN {CoverHashTab}
  581.       L := Arg.LocLvl + 1;
  582.       H := AddrHash(CvrUnitPt,Arg.LocLL);
  583.       HLim := (H^.Bas DIV SizeOf(LL));
  584.       WITH H^ DO FOR I := 0 TO HLim DO
  585.            IF Slt[I] <> 0 THEN Push(Slt[I],Arg.LocOwn,cvName,L);
  586.    END; {CoverHashTab}
  587.  
  588. Begin {CalcCovers}                                              {.CP25}
  589.  
  590.    With CvrUnitPt^ Do Begin
  591.       Push(UHIHT,UHUDH,cvHash,0);         { INTERFACE Hash Table  }
  592.       Push(UHUDH,0,cvName,1);             { Unit Dictionary Entry }
  593.       IF UHIHT <> UHDHT
  594.          THEN Push(UHDHT,UHDHT,cvHash,0); { Debug Rtn Hash Table  }
  595.    End;
  596.  
  597.    WITH CvrWork DO
  598.    WHILE CvrStkTop > 0 DO BEGIN
  599.       Pop(CvrWork);
  600.       IF NOT Queued(LocLL) THEN
  601.       BEGIN
  602.          EnQueue(CvrWork);
  603.          CASE LocTyp OF
  604.              cvName: CoverDictHdr(CvrWork); {DictHdr}
  605.          cvHash: CoverHashTab(CvrWork); {HashTab}
  606.          cvType: CoverType(CvrWork);    {TypDesc}
  607.          END; {CASE}
  608.       END; {IF}
  609.    END; {WHILE}
  610.    CoverWrapUp;
  611.  
  612. End;  {CalcCovers}
  613.  
  614.                                                                 {.PA} {
  615.   The following method uses the output of method "CalcCovers" to browse the
  616.   symbol dictionary and discover relations involving the CSeg Map, the PROC
  617.   Map, the Global VAR DSeg Map and the Typed CONST DSeg Map.  The relations
  618.   can involve Fix-Up data, the Trace Table, the Source File List, and the
  619.   various code and data segments contained in the latter part of the unit
  620.   file.  These relations are saved in the heap for later retrieval by the
  621.   print routines.
  622. }
  623.  
  624. Procedure Cover.IndexMaps;                                      {.CP03}
  625.  
  626. Var  CodeBase, DataBase, FixCBase, FixDBase : Word;
  627.  
  628.    { This Procedure computes the size of each }                 {.CP24}
  629.    { PROC and adds the result to the Xref map }
  630.  
  631.    Procedure SizeProcs;
  632.    Var CodeLimit, I, J, K : Word; Pc, Pp : MapTabPtr; Rp, Rc : RMapPtr;
  633.    Begin
  634.       I := 0;
  635.       CodeLimit := (CvrUnitPt^.UHENC+$F) AND $FFF0 + CvrUnitPt^.UHZCS;
  636.       Rp := CvrMapPtr^.TMapProPtr;     { Get RMap Pro Pointer }
  637.       Pp := Rp^.RMapTabPtr;            { Get Proc Ref Pointer }
  638.       J  := Rp^.RMapTabSiz;            { Get Slot Count       }
  639.       Rc := CvrMapPtr^.TMapCodPtr;     { Get RMap Cod Pointer }
  640.       Pc := Rc^.RMapTabPtr;            { Get CSeg Ref Pointer }
  641.       While I < J-1 Do With Pp^[I] Do Begin
  642.          If Pp^[I].MapCSM <> $FFFF Then
  643.            If Pp^[I].MapCSM = Pp^[I+1].MapCSM
  644.            Then Pp^[I].MapSiz := Pp^[I+1].MapEPT - Pp^[I].MapEPT
  645.            Else Begin
  646.              K := Pp^[I].MapCSM DIV SizeOf(CMapRec);
  647.              Pp^[I].MapSiz := Pc^[K].MapLod + Pc^[K].MapSiz - Pp^[I].MapEPT;
  648.            End;
  649.          Inc(I);
  650.       End;
  651.       With Pp^[J-1] Do
  652.       If MapCSM <> $FFFF
  653.       Then MapSiz := Codelimit - MapEPT;
  654.    End; {SizeProcs}
  655.  
  656.    { This Procedure Initializes the CSeg Xref Map }             {.CP29}
  657.    { and sets CSeg Load Points and Fix-Up Offsets }
  658.  
  659.    Procedure PrimeCSegs;
  660.    Var Cx, Cn, I, N : Word; D : DMapTabPtr;
  661.        C : CMapTabPtr; P : PMapPtr; Rmt, Rmv : MapTabPtr;
  662.    Begin
  663.       Rmt := CvrMapPtr^.TMapCodPtr^.RMapTabPtr;
  664.       N   := CvrMapPtr^.TMapCodPtr^.RMapTabSiz;
  665.       Cn  := CountCMapSlots(CvrUnitPt);
  666.       C   := AddrCMapTab(CvrUnitPt);
  667.  
  668.       If C <> Nil Then
  669.       For Cx := 0 To Cn-1 Do    { First, we add Info from CSeg  }
  670.       With C^[Cx], Rmt^[Cx] Do  { Map to our CSeg MapRefTab and }
  671.       Begin                     { Calc Fix-Up Offsets           }
  672.          MapTyp := mfCSEG;
  673.          MapSrc := 0;
  674.          MapLod := CodeBase;
  675.          MapSiz := CSegCnt;
  676.          Inc(CodeBase,CSegCnt);
  677.          If CSegRel > 0 Then    { We Have Fix-Ups for this CSeg }
  678.          Begin
  679.             MapFxI := FixCBase;
  680.             FixCBase := FixCBase + CSegRel;
  681.             MapFxJ := FixCBase - SizeOf(FixUpRec);
  682.          End;
  683.       End;
  684.  
  685.       { Now, we do a similar job for Typed Constant Data Segments }
  686.  
  687.       Rmv := CvrMapPtr^.TMapConPtr^.RMapTabPtr;
  688.       N   := CvrMapPtr^.TMapConPtr^.RMapTabSiz;
  689.       D   := AddrDMapTab(CvrUnitPt);
  690.  
  691.       If D <> Nil Then
  692.       For Cx := 0 To N-1 Do     { First, we add Info from DSeg  }
  693.       With D^[Cx], Rmv^[Cx] Do  { Map to our DSeg MapRefTab and }
  694.       Begin                     { Calc Fix-Up Offsets           }
  695.          MapSrc := 0;
  696.          MapSiz := DSegCnt;
  697.          MapFxJ := DSegRel;
  698.          If DSegOwn <> 0 Then
  699.          Begin MapOwn := DSegOwn; MapTyp := mfTVMT End;
  700.       End;
  701.  
  702.       { Now, we do a similar job for the PROC Map }
  703.  
  704.       Rmv := CvrMapPtr^.TMapProPtr^.RMapTabPtr;
  705.       N   := CvrMapPtr^.TMapProPtr^.RMapTabSiz;
  706.       P   := AddrPMapTab(CvrUnitPt);
  707.  
  708.       If P <> Nil Then
  709.       For Cx := 0 To N-1 Do
  710.       With P^[Cx], Rmv^[Cx] Do
  711.       Begin
  712.          MapCSM := CSegOfs;
  713.          MapEPT := CSegJmp;
  714.          If MapCSM <> $FFFF Then
  715.          Begin
  716.             MapTyp := mfPROC;
  717.             I := MapCSM DIV SizeOf(CMapRec);
  718.             MapEPT := MapEPT + Rmt^[I].MapLod;  { Relocate Entry Point }
  719.          End;
  720.          MapSrc := 0;
  721.       End;
  722.  
  723.    End; { PrimeCSegs }
  724.  
  725.    { This Procedure updates the CSeg Xref Table with information }{.CP57}
  726.    { from the Trace and PROC Tables that allow us to determine   }
  727.    { which of the source files contained the CSeg represented by }
  728.    { the map entry.                                              }
  729.  
  730.    Procedure FinalCSegs;
  731.    Var Cx, Cn, I, N, Sf, Sn, So : Word;
  732.        Sp, Sh : SrcFilePtr; Tp : TraceRecPtr; Rmt, Rmv : MapTabPtr;
  733.    Begin
  734.       Rmt:= CvrMapPtr^.TMapCodPtr^.RMapTabPtr;
  735.       Cn := CvrMapPtr^.TMapCodPtr^.RMapTabSiz;
  736.       Sh := AddrSrcTabOff(CvrUnitPt,0); Sp := Sh;  { Source File List }
  737.       Sf := 0;   { Total Source Files   }
  738.       Sn := 0;   { Total Non-.OBJ Files }
  739.       While Sp <> Nil Do Begin
  740.          Inc(Sf);                               { Inc Total Source Files }
  741.          If Sp^.SrcFlag <> $05 Then Inc(Sn);    { Inc Non-Obj File Count }
  742.          Sp := AddrNxtSrc(CvrUnitPt,Sp);
  743.       End;
  744.       So := Sf - Sn;    { Total *.OBJ Files }
  745.       Sp := Sh;         { Restore Sp        }
  746.  
  747.       If So > 0 Then    { There ARE *.OBJ Files in Source File List }
  748.       Begin             
  749.          For I := 1 to Sn Do Sp := AddrNxtSrc(CvrUnitPt,Sp);
  750.          Cx := Cn - So;            { 1st CMap Entry from .OBJ File  }
  751.          For I := Cx To Cn-1 Do
  752.          With Rmt^[I] Do
  753.          Begin
  754.             MapSrc := FormLL(Sh,Sp);
  755.             Sp := AddrNxtSrc(CvrUnitPt,Sp);
  756.          End;
  757.       End;              { *.OBJ Handler }
  758.  
  759.       { If Pascal Include Files are present, Only the Trace Table Knows }
  760.       { and this is noted only if these files contain PROCs.  This can  }
  761.       { be used to get the source file (actual) in these cases.  Scan   }
  762.       { the trace table and compare its PROC pointer with PROC Name LL  }
  763.       { in our PROC Ref table.  If match, then trace entry has source   }
  764.       { info that applies to this proc (which is part of some CSeg) and }
  765.       { the PROC Ref entry has the CSeg Map Offset which we use to make }
  766.       { the linkage to our CSeg Ref table to save source file offset.   }
  767.  
  768.       Tp := AddrTraceTab(CvrUnitPt);
  769.       Rmv := CvrMapPtr^.TMapProPtr^.RMapTabPtr;
  770.       N   := CvrMapPtr^.TMapProPtr^.RMapTabSiz;
  771.       While Tp <> Nil Do With Tp^ Do Begin      {For ALL Trace Entries}
  772.          I := 0;
  773.          While I < N Do With Rmv^[I] Do Begin   {For ALL PROC Map Entries}
  774.             If MapOwn = Trname Then             {Proc has a Trace Entry  }
  775.             Begin
  776.                Rmt^[MapCSM DIV SizeOf(CMapRec)].MapSrc := Trfill; {CSeg Refs}
  777.                I := N;   {quit loop and try next trace entry}
  778.             End;
  779.             Inc(I);
  780.          End;
  781.          Tp := AddrNxtTrace(CvrUnitPt,Tp);
  782.       End;
  783.    End;  {FinalCSegs}
  784.  
  785.    { This Procedure updates the CONST Xref Table with data from   }{.CP46}
  786.    { various sources to get offsets to Fix-Up data and to try to  }
  787.    { locate the file in the Source File List that contributed     }
  788.    { this entry.  Any entry NOT defined in the Pascal Source will }
  789.    { have mfNULL as its MapTyp.  We will change such entries to   }
  790.    { mfXTRN and try to decide who spawned them.  This problem is  }
  791.    { strictly undecidable.  We can guess that a Fix-Up in some    }
  792.    { CSeg that references our entry is from the *.OBJ spawned the }
  793.    { block, but that is the closest we can get to the truth.      }
  794.  
  795.    Procedure FinalCONST;
  796.    Var I, N : Integer; HaveXtrn : Boolean; Rmt : MapTabPtr;
  797.    Begin
  798.       Rmt := CvrMapPtr^.TMapConPtr^.RMapTabPtr;
  799.       N   := CvrMapPtr^.TMapConPtr^.RMapTabSiz;
  800.       HaveXtrn := False;
  801.  
  802.       If N > 0 Then
  803.       Begin
  804.          For I := 0 To N-1 Do With Rmt^[I] Do Begin
  805.             MapLod := DataBase;
  806.             DataBase := DataBase + MapSiz;
  807.             If MapFxJ > 0 Then
  808.             Begin
  809.                MapFxI := FixDBase;
  810.                Inc(FixDBase,MapFxJ);
  811.                MapFxJ := FixDBase - SizeOf(FixUpRec);
  812.             End;
  813.             If MapTyp = mfNULL Then
  814.             Begin
  815.               MapTyp := mfXTRN;
  816.               HaveXtrn := True;
  817.             End;
  818.          End;          { Fix-Up Offsets are now set }
  819.          { Source File problem deferred until later }
  820.       End;
  821.  
  822.       Rmt := CvrMapPtr^.TMapVarPtr^.RMapTabPtr;  { Classify VARS Too }
  823.       N   := CvrMapPtr^.TMapVarPtr^.RMapTabSiz;
  824.       If N > 0 Then
  825.       Begin
  826.          For I := 0 To N-1 Do With Rmt^[I] Do
  827.            If MapTyp = mfNULL Then MapTyp := mfXTRN
  828.       End;
  829.  
  830.    End;  {FinalCONST}
  831.  
  832. Var I, J, DHT : Word; C : Char; SystemUnit, InINTF : Boolean;       {.CP26}
  833.     Pn : DNamePtr; Ps : DStubPtr; Pv : VarStubPtr; Pm, Pc : RMapPtr;
  834.     Pp : PMapRecPtr; Tc, Tv, Td : DMapRecPtr; V : CvrRec; Q, Qc : MapRefRec;
  835.  
  836. Begin {IndexMaps}
  837.  
  838.    If CvrMapPtr <> Nil Then CvrMapPtr^.Done;
  839.    CvrMapPtr := New(TMapPtr,Init(CvrUnitPt));
  840.  
  841.    CodeBase   := (CvrUnitPt^.UHENC + $F) AND $FFF0;
  842.    DataBase   := (CvrUnitPt^.UHZCS + CodeBase +$F) AND $FFF0;
  843.    FixCBase   := (CvrUnitPt^.UHZDT + DataBase +$F) AND $FFF0;
  844.    DHT        :=  CvrUnitPt^.UHDHT;
  845.    SystemUnit :=  IsSystemUnit(CvrUnitPt);
  846.  
  847.    If CvrMapPtr^.TMapCodPtr^.RMapTabSiz > 0 { Initialize CSeg Map Refs }
  848.    Then PrimeCSegs;
  849.  
  850.    FixDBase := (FixCBase +$F) AND $FFF0;  { VMT Fix-Ups Start Here }
  851.    Pc := CvrMapPtr^.TMapCodPtr;           { Get Method Pointer }
  852.  
  853.    For I := 1 To CvrQueTail Do Begin    { Get CONST/VAR Mapping }
  854.       V := CvrQuePtr^[I];
  855.       If V.LocTyp = cvName Then
  856.       Begin
  857.          Pn := Ptr(Seg(CvrUnitPt^),Ofs(CvrUnitPt^)+V.LocLL);
  858.          Tc := Ptr(Seg(CvrUnitPt^),Ofs(CvrUnitPt^)+CvrUnitPt^.UHTMT);
  859.          Tv := Ptr(Seg(CvrUnitPt^),Ofs(CvrUnitPt^)+CvrUnitPt^.UHDMT);
  860.          Ps := AddrStub(Pn);
  861.          C := Public(Pn^.DForm);
  862.  
  863.          If C = 'R' Then    { a data instance of some kind }    {.CP42}
  864.          Begin
  865.             If Ps^.sRAM < $02 Then { a global variable or typed const }
  866.             Begin
  867.                Pv := @Ps^.sRVF;
  868.                J := Pv^.TOB;
  869.                InINTF := (DHT > V.LocLL) OR SystemUnit;
  870.  
  871.                If Ps^.sRAM = $00 Then   { it's a Global Variable }
  872.                Begin                    
  873.                   Pm := CvrMapPtr^.TMapVarPtr;
  874.                   Pm^.FetchRef(Q,Pv^.TOB);
  875.                   Td := Ptr(Seg(Tv^),Ofs(Tv^)+Pv^.TOB);
  876.                   Q.MapSiz := Td^.DSegCnt;
  877.                   If InINTF Then Q.MapTyp := mfINTF
  878.                             Else Q.MapTyp := mfIMPL;
  879.                   Pm^.StoreRef(Q,Pv^.TOB);
  880.                End
  881.                Else                     { it's a Typed Constant  }
  882.                Begin
  883.                   Pm := CvrMapPtr^.TMapConPtr;
  884.                   Pm^.FetchRef(Q,Pv^.TOB);
  885.                   Td := Ptr(Seg(Tc^),Ofs(Tc^)+Pv^.TOB);
  886.                   If Td^.DSegOwn <> 0 Then
  887.                   Begin
  888.                      Q.MapTyp := mfTVMT;
  889.                      Q.MapOwn := Td^.DSegOwn;   { Owner is OBJECT Name  }
  890.                   End Else
  891.                   If V.LocLvl = 1 Then
  892.                      If InINTF Then Q.MapTyp := mfINTF
  893.                                Else Q.MapTyp := mfIMPL
  894.                   Else
  895.                   Begin
  896.                      Q.MapTyp := mfNEST;
  897.                      Q.MapOwn := V.LocOwn;      { Owner is PROC scope   }
  898.                   End;
  899.                   Pm^.StoreRef(Q,Pv^.TOB);
  900.                End;   { Typed Constant    }
  901.             End;      { Variable/Constant }
  902.          End          { Type 'R' Stub     }
  903.  
  904.          Else                             { Check for PROC Map } {.CP27}
  905.          If C = 'S' Then                  { It's a PROC ...... }
  906.          If (Ps^.sSTP AND $02) = 0 Then   { ... But NOT INLINE }
  907.          Begin
  908.             Pm := CvrMapPtr^.TMapProPtr;  { Get Method Pointer }
  909.             Pm^.FetchRef(Q,Ps^.sSPM);
  910.             Q.MapOwn := V.LocLL;         { Get PROC Name Offset }
  911.             Pm^.StoreRef(Q,Ps^.sSPM);
  912.          End;  { Type 'S' Stub }
  913.       End;     { DName Entry   }
  914.    End;        { FOR           }
  915.  
  916.    If CvrMapPtr^.TMapCodPtr^.RMapTabSiz > 0  { Finish Up CSeg Map Refs }
  917.    Then FinalCSegs;
  918.  
  919.    CvrMapPtr^.TMapProPtr^.SortPMap(CSegOrder);   { Sort into Load Order  }
  920.    SizeProcs;                                    { Get Proc Size(Bytes)  }
  921.    CvrMapPtr^.TMapProPtr^.SortPMap(PMapOrder);   { Sort into PMap Order  }
  922.    FinalCONST;                                   { Finish CONST Map Refs }
  923.  
  924. End; {IndexMaps}
  925.  
  926.       (*   E N D    M E T H O D S   *)
  927.  
  928. Function FindCover(U : UnitPtr; S : CoverPtr) : CoverPtr;       {.CP11}
  929. Begin
  930.    FindCover := Nil;
  931.    While S <> Nil Do
  932.      If S^.CvrUnitPt = U Then
  933.      Begin
  934.         FindCover := S;
  935.         S := Nil
  936.      End
  937.      Else S := S^.CvrNxtPtr
  938. End; {FindCover}
  939.  
  940. PROCEDURE FetchVARsRef  (VAR S : MapRefRec;                     {.CP09}
  941.                            U   : UnitPtr;
  942.                          Offset: Word);
  943. Var Q : CoverPtr;
  944. Begin
  945.    Q := FindCover(U,CvrRoot);
  946.    If Q <> Nil
  947.    Then Q^.CvrMapPtr^.TMapVarPtr^.FetchRef(S,Offset);
  948. End;
  949.  
  950. PROCEDURE FetchCSegRef  (VAR S : MapRefRec;                     {.CP09}
  951.                            U   : UnitPtr;
  952.                          Offset: Word);
  953. Var Q : CoverPtr;
  954. Begin
  955.    Q := FindCover(U,CvrRoot);
  956.    If Q <> Nil
  957.    Then Q^.CvrMapPtr^.TMapCodPtr^.FetchRef(S,Offset);
  958. End;
  959.  
  960. PROCEDURE FetchProcRef  (VAR S : MapRefRec;                     {.CP09}
  961.                            U   : UnitPtr;
  962.                          Offset: Word);
  963. Var Q : CoverPtr;
  964. Begin
  965.    Q := FindCover(U,CvrRoot);
  966.    If Q <> Nil
  967.    Then Q^.CvrMapPtr^.TMapProPtr^.FetchRef(S,Offset);
  968. End;
  969.  
  970. PROCEDURE SortProcRefs  (  U   : UnitPtr;
  971.                          Mode  : SortMode);
  972. Var Q : CoverPtr;
  973. Begin
  974.    Q := FindCover(U,CvrRoot);
  975.    If Q <> Nil
  976.    Then Q^.CvrMapPtr^.TMapProPtr^.SortPmap(Mode);
  977. End;
  978.  
  979. PROCEDURE FetchCONsRef  (VAR S : MapRefRec;                     {.CP09}
  980.                            U   : UnitPtr;
  981.                          Offset: Word);
  982. Var Q : CoverPtr;
  983. Begin
  984.    Q := FindCover(U,CvrRoot);
  985.    If Q <> Nil
  986.    Then Q^.CvrMapPtr^.TMapConPtr^.FetchRef(S,Offset);
  987. End;
  988.  
  989. PROCEDURE FetchNextSurvey (U : UnitPtr; VAR S : SurveyRec);     {.CP23}
  990. Var Q : CvrRec;
  991. Begin
  992.    S.LocTyp := cvNULL; S.LocLL  := 0; S.LocOwn := 0; S.LocNxt := 0;
  993.    If CvrRoot <> Nil Then
  994.    Begin
  995.       If CvrLocus = Nil Then CvrLocus := CvrRoot;
  996.       If CvrLocus^.CvrUnitPt <> U
  997.       Then CvrLocus := FindCover(U,CvrRoot);
  998.       If CvrLocus <> Nil Then With CvrLocus^ Do
  999.       Begin
  1000.          If CvrQueHead < CvrQueTail Then
  1001.          Begin
  1002.             Inc(CvrQueHead);
  1003.             Q := CvrQuePtr^[CvrQueHead];
  1004.             S.LocTyp := Q.LocTyp; S.LocLL  := Q.LocLL;
  1005.             S.LocOwn := Q.LocOwn; S.LocNxt := U^.UHPMT
  1006.          End;
  1007.          If CvrQueHead < CvrQueTail
  1008.          Then S.LocNxt := CvrQuePtr^[CvrQueHead+1].LocLL;
  1009.       End;
  1010.    End;
  1011. End; {FetchNextSurvey}
  1012.  
  1013. Procedure PurgeUnitSurvey(U : UnitPtr);                             {.CP18}
  1014. Var P, Q, R : CoverPtr;
  1015. Begin
  1016.    P := Nil;
  1017.    Q := FindCover(U,CvrRoot);
  1018.    If Q <> Nil Then
  1019.    Begin
  1020.       P := Q^.CvrNxtPtr;
  1021.       R := CvrRoot;
  1022.       If Q = R
  1023.       Then CvrRoot := P Else
  1024.       Begin
  1025.         While R^.CvrNxtPtr <> Q Do R := R^.CvrNxtPtr;
  1026.         R^.CvrNxtPtr := P;
  1027.       End;
  1028.       Q^.Done;
  1029.    End;
  1030. End; {PurgeUnitSurvey}
  1031.  
  1032. PROCEDURE SurveyUnit(U : UnitPtr);            {.CP15}
  1033. Var S : CoverPtr;
  1034. BEGIN  {SurveyUnit}
  1035.    PurgeUnitSurvey(U);                  { Make sure no left-overs }
  1036.    CvrRoot := New(CoverPtr,
  1037.                   Init(U,CvrRoot));     { Build new Instance      }
  1038.    CvrRoot^.CalcCovers;                 { Analyze Dictionary      }
  1039.    CvrRoot^.DisposeStack;               { Release Cover Stack     }
  1040.    CvrRoot^.PackQueue;                  { Trim Cover Queue        }
  1041.    CvrRoot^.IndexMaps;                  { Cross-Index All Maps    }
  1042. END;   {SurveyUnit}
  1043.  
  1044. END.  { TPU6TST }